package cn.zebra.dev.pay.module.wechat.service;

import cn.hutool.core.date.DateUtil;
import cn.zebra.dev.common.utils.StrUtils;
import cn.zebra.dev.config.pay.wechat.LocalPaymentKit;
import cn.zebra.dev.config.pay.wechat.WeChatPayConfigureBean;
import cn.zebra.dev.pay.module.wechat.entity.CreateOrderEntity;
import com.jpay.ext.kit.IpKit;
import com.jpay.ext.kit.PaymentKit;
import com.jpay.ext.kit.StrKit;
import com.jpay.weixin.api.WxPayApi;
import com.jpay.weixin.api.WxPayApiConfig;
import com.jpay.weixin.api.WxPayApiConfigKit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.Map;

/**
 * @author runnable@sina.cn
 */
@Service
@Slf4j
public class WeChatPayService {

    @Autowired
    private WeChatPayConfigureBean config;

    private static final String
            SUCCESS = "SUCCESS",
            RETURN_CODE = "return_code",
            RETURN_MSG = "return_msg",
            TRADE_STATE = "trade_state",
            REFUND = "REFUND",
            NOTPAY = "NOTPAY",
            CLOSED = "CLOSED",
            REVOKED = "REVOKED",
            USERPAYING = "USERPAYING",
            PAYERROR = "PAYERROR",
            PREPAY_ID = "prepay_id";

    /**
     * 查询订单(微信订单号或商户订单号二传一)
     *
     * @param transactionId 微信订单号 优先使用
     * @param outTradeNo    商户订单号
     * @return api返回信息
     */
    public String queryOrder(String transactionId, String outTradeNo) {
        if (StrUtils.isBlank(transactionId) && StrUtils.isBlank(outTradeNo)) {
            throw new RuntimeException("请传递微信订单号或商户订单号!");
        }
        WxPayApiConfig wxPayApiConfig = WxPayApiConfig.New()
                .setAppId(config.getAppId())
                .setMchId(config.getMchId())
                .setPaternerKey(config.getPaternerKey())
                .setOutTradeNo(outTradeNo);
        String xmlResult = WxPayApi.orderQuery(config.getDev(), wxPayApiConfig.orderQueryBuild());
        Map<String, String> resultMap = PaymentKit.xmlToMap(xmlResult);
        if (!SUCCESS.equals(resultMap.get(RETURN_CODE))) {
            return resultMap.get(RETURN_MSG);
        }
        String tradeState = resultMap.get(TRADE_STATE);
        switch (tradeState) {
            case SUCCESS:
                return "支付成功";
            case REFUND:
                return "转入退款";
            case NOTPAY:
                return "未支付";
            case CLOSED:
                return "已关闭";
            case REVOKED:
                return "已撤销（刷卡支付）";
            case USERPAYING:
                return "用户支付中";
            case PAYERROR:
                return "支付失败(其他因素)";
            default:
                return "未知信息";
        }
    }

    /**
     * 统一下单
     *
     * @param entity 下单参数
     */
    public String create(CreateOrderEntity entity) {
        WxPayApiConfig wxPayApiConfig = WxPayApiConfig.New()
                .setAppId(config.getAppId())
                .setMchId(config.getMchId())
                .setPaternerKey(config.getPaternerKey())
                .setBody(entity.getBody())
                .setOutTradeNo(entity.getOutTradeNo())
                .setTotalFee(entity.getTotalFee().setScale(2, RoundingMode.DOWN).toString())
                .setSpbillCreateIp(entity.getIp())
                .setNotifyUrl(entity.getNotifyUrl())
                .setTradeType(WxPayApi.TradeType.APP);
        String xmlResult = WxPayApi.pushOrder(config.getDev(), wxPayApiConfig.orderQueryBuild());
        Map<String, String> resultMap = PaymentKit.xmlToMap(xmlResult);
        if (!SUCCESS.equals(resultMap.get(RETURN_CODE))) {
            return resultMap.get(RETURN_MSG);
        }
        return resultMap.get(PREPAY_ID);
    }

    /**
     * 关闭订单(不支持沙盒)
     *
     * @param outTradeNo 商户订单号
     * @return 微信方返回信息
     */
    public String close(String outTradeNo) {
        WxPayApiConfig wxPayApiConfig = WxPayApiConfig.New()
                .setAppId(config.getAppId())
                .setMchId(config.getMchId())
                .setPaternerKey(config.getPaternerKey())
                .setOutTradeNo(outTradeNo);
        String xmlResult = WxPayApi.closeOrder(wxPayApiConfig.orderQueryBuild());
        Map<String, String> resultMap = PaymentKit.xmlToMap(xmlResult);
        return resultMap.get(RETURN_MSG);
    }

    public Map<String, String> wxPay(BigDecimal totalMoney, HttpServletRequest request, Integer userId, String orderNo, String body) {
        WxPayApiConfig wxPayApiConfig = WxPayApiConfig.New()
                .setAppId("wxc89994277a171f4a")
                .setMchId("1564296871")
                .setPaternerKey("CwWnO9cp999BHwmBJ6zkAH7F6HwV3Rqz")
                .setPayModel(WxPayApiConfig.PayModel.BUSINESSMODEL);
        WxPayApiConfigKit.setThreadLocalWxPayApiConfig(wxPayApiConfig);

        // 不用设置授权目录域名
        // 统一下单地址 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1#
        String ip = IpKit.getRealIp(request);
        if (StrKit.isBlank(ip)) {
            ip = "127.0.0.1";
        }
        Date payExpirationTime = DateUtil.offsetMinute(new Date(), 30);
        Map<String, String> params = WxPayApiConfigKit
                .getWxPayApiConfig()
                .setAttach("兵哥环保支付")
                .setBody(body)
                .setSpbillCreateIp(ip).setTotalFee(String.valueOf(totalMoney))
                .setTradeType(WxPayApi.TradeType.APP)
                .setNotifyUrl("http://www.xbghb.com/api/member/api/pay/appWxRechargeNotify")
                .setOutTradeNo(orderNo)
                .setTimeExpire(DateUtil.format(payExpirationTime, "yyyyMMddHHmmss"))
                .build();
        String xmlResult = WxPayApi.pushOrder(false, params);
        log.info(xmlResult);
        Map<String, String> resultMap = PaymentKit.xmlToMap(xmlResult);

        String return_code = resultMap.get("return_code");
        String return_msg = resultMap.get("return_msg");
        if (!PaymentKit.codeIsOK(return_code)) {
            return null;
        }
        // 以下字段在return_code 和result_code都为SUCCESS的时候有返回
        String prepay_id = resultMap.get("prepay_id");
        // 封装调起微信支付的参数 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_12
        Map<String, String> packageParams = LocalPaymentKit.prepayIdCreateSignByApp(prepay_id);
        log.info("最新返回apk的参数:" + packageParams);
        return packageParams;

    }

    public Map<String, String> wxPayBalance(BigDecimal totalMoney, HttpServletRequest request, Integer userId, String orderNo, String body) {
        WxPayApiConfig wxPayApiConfig = WxPayApiConfig.New()
                .setAppId("wxc89994277a171f4a")
                .setMchId("1564296871")
                .setPaternerKey("CwWnO9cp999BHwmBJ6zkAH7F6HwV3Rqz")
                .setPayModel(WxPayApiConfig.PayModel.BUSINESSMODEL);
        WxPayApiConfigKit.setThreadLocalWxPayApiConfig(wxPayApiConfig);

        // 不用设置授权目录域名
        // 统一下单地址 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1#
        String ip = IpKit.getRealIp(request);
        if (StrKit.isBlank(ip)) {
            ip = "127.0.0.1";
        }
        Date payExpirationTime = DateUtil.offsetMinute(new Date(), 30);
        Map<String, String> params = WxPayApiConfigKit
                .getWxPayApiConfig()
                .setAttach("兵哥环保支付")
                .setBody(body)
                .setSpbillCreateIp(ip).setTotalFee(String.valueOf(totalMoney))
                .setTradeType(WxPayApi.TradeType.APP)
                .setNotifyUrl("http://www.xbghb.com/api/member/api/pay/appWxRechargeNotifyBalance")
                .setOutTradeNo(orderNo)
                .setTimeExpire(DateUtil.format(payExpirationTime, "yyyyMMddHHmmss"))
                .build();
        String xmlResult = WxPayApi.pushOrder(false, params);
        log.info(xmlResult);
        Map<String, String> resultMap = PaymentKit.xmlToMap(xmlResult);

        String return_code = resultMap.get("return_code");
        String return_msg = resultMap.get("return_msg");
        if (!PaymentKit.codeIsOK(return_code)) {
            return null;
        }
        // 以下字段在return_code 和result_code都为SUCCESS的时候有返回
        String prepay_id = resultMap.get("prepay_id");
        // 封装调起微信支付的参数 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_12
        Map<String, String> packageParams = LocalPaymentKit.prepayIdCreateSignByApp(prepay_id);
        log.info("最新返回apk的参数:" + packageParams);
        return packageParams;

    }
}
